﻿using System;
using System.Collections.Generic;
using IM.Interfaces.Protocols;
using System.Reflection;
using System.IO;
using IM.Interfaces;

namespace IM.Protocols
{
    public class ProtocolAdapter : IProtocolAdapter
    {
        public bool IsProtocolCreated
        {
            get;
            private set;
        }

        public bool IsSettingsCreated
        {
            get;
            private set;
        }

        public IProtocol Protocol
        {
            get;
            private set;
        }

        public IProtocolSettings Settings
        {
            get;
            private set;
        }

        public ProtocolAdapter(String name, String path)
        {
            Assembly asm = System.Reflection.Assembly.LoadFile(Path.GetFullPath(path));

            InitProtocol(name, asm);
            InitSettings(asm);

        }

        private void InitProtocol(String name, Assembly asm)
        {
			if (string.IsNullOrEmpty(name))	
				throw new NullReferenceException("Name is undefined");
			if (asm == null)
				throw new NullReferenceException("Target assembly is null");
			
            Type iProtocol1Type = typeof(IProtocol);

			Type[] types;
            try
            {
            	types = asm.GetExportedTypes();
            }
            catch (Exception ex)
            {
            	throw new ProtocolException("Exception while getting types from an assmebly:\n" + ex.Message, name, ex);
            }

            try
            {
            	foreach (var type in types)
	            {
	                if (iProtocol1Type.IsAssignableFrom(type))
	                {
	                    this.Protocol = Activator.CreateInstance(type, new Object[] {name}) as IProtocol;
	                    this.IsProtocolCreated = true;
	                    return;
	                }
	            }
            }
            catch (Exception ex)
            {
				Logging.Logger.AddException(ex);
            	throw new ProtocolException(string.Format("Exception, while activating protocol {0}:\n{1} ", 
				                                          name, ex.Message), name, ex);
            }

            this.IsProtocolCreated = false;
        }

        private void InitSettings(Assembly asm)
        {
            Type iProtocol1Type = typeof(IProtocolSettings);

            Type[] types = asm.GetExportedTypes();

            foreach (var type in types)
            {
                if (iProtocol1Type.IsAssignableFrom(type))
                {
                    this.Settings = Activator.CreateInstance(type) as IProtocolSettings;
                    this.IsSettingsCreated = true;
                    return;
                }
            }

            this.IsSettingsCreated = false;
        }

        public void DestroyAdapter()
        {
            this.Protocol.Logout();
        }

        public void LoadSettings()
        {
            this.Protocol.LoadSettingsData(this.Settings.GetSettingsData(this.Protocol.GetSettingsData()));
        }
    }
}
